module Game.Trubis.Field where

import Game.Trubis.Position
import Game.Trubis.PipeSection
import Data.Array
import Data.Array.ST
import Data.Maybe

type Field = Array Position (Maybe PipeSection)

-- | @mkEmptyField (lowerLeftCorner, upperRightCorner)@ makes a `Field`
-- of `Nothing` with specified bounds.
mkEmptyField :: (Position, Position) -> Field
mkEmptyField bounds = runSTArray $ newArray bounds Nothing

blocked :: Position -> Field -> Bool
blocked pos f = not (inRange (bounds f) pos) || isJust (f ! pos)

-- | Removes `PipeSection`s from `Field` at specified `Position`s
-- (i. e. sets values at those `Position`s to `Nothing`).
(\\) :: Field -> [Position] -> Field
f \\ ps = f // map (,Nothing) ps

-- | Let some item has `Position` @p@ and it is falling `down` over `Field` @f@.
-- Eventually the item will be `blocked` and will stop at @fallPos f p@.
fallPos :: Field -> Position -> Position
fallPos f = last . takeWhile (not . (`blocked` f)) . iterate (^+^ down)

